using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Runtime.InteropServices;
using System.Security;
using System.Net;
using System.ServiceProcess;
using System.Net.Sockets;
using System.Diagnostics;
using System.Net.NetworkInformation;

namespace UselessExplorer
{
    public partial class frmNetwrkStatus : Form
    {
        public frmNetwrkStatus()
        {
            InitializeComponent();
        }
       // int IndexDG = 0;
        string invalidIP = "No such host is known";
        
        private void frmNetwrkStatus_Load(object sender, EventArgs e)
        {
            bwNetworkStatus.RunWorkerAsync();
            this.Text = this.Text + " - " + "Scanning Network";
        }

        private string GetIPAddress(string HostName)
        {
            try
            {
                IPAddress[] addresslist = Dns.GetHostAddresses(HostName);
                foreach (IPAddress theaddress in addresslist)
                {
                    return theaddress.ToString();
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

            return String.Empty;
        }

        private string CheckHttpStatus(string HostName)
        {
            try
            {
                ServiceController IIS = new ServiceController("IIS Admin", HostName);
                if (IIS.Status.ToString().Equals("Running"))
                    return IIS.Status.ToString();
            }
            catch (Exception)
            {

            }
            return "Unavailable";
        }

        //declare the Netapi32 : NetServerEnum method import
        [DllImport("Netapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]

        /// <summary>
        /// Netapi32.dll : The NetServerEnum function lists all servers
        /// of the specified type that are visible in a domain. For example, an 
        /// application can call NetServerEnum to list all domain controllers only
        /// or all SQL servers only. You can combine bit masks to list
        /// several types. For example, a value of 0x00000003  combines the bit
        /// masks for SV_TYPE_WORKSTATION (0x00000001) and SV_TYPE_SERVER (0x00000002)
        /// </summary>
        public static extern int NetServerEnum(
            string ServerNane, // must be null
            int dwLevel,
            ref IntPtr pBuf,
            int dwPrefMaxLen,
            out int dwEntriesRead,
            out int dwTotalEntries,
            int dwServerType,
            string domain, // null for login domain
            out int dwResumeHandle
            );

        //declare the Netapi32 : NetApiBufferFree method import
        [DllImport("Netapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]

        /// <summary>
        /// Netapi32.dll : The NetApiBufferFree function frees 
        /// the memory that the NetApiBufferAllocate function allocates. 
        /// Call NetApiBufferFree to free the memory that other network 
        /// management functions return.
        /// </summary>
        public static extern int NetApiBufferFree(IntPtr pBuf);

        //create a _SERVER_INFO_100 STRUCTURE

        [StructLayout(LayoutKind.Sequential)]
        public struct _SERVER_INFO_100
        {
            internal int sv100_platform_id;
            [MarshalAs(UnmanagedType.LPWStr)]
            internal string sv100_name;
        }

        /// <summary>
        /// Uses the DllImport : NetServerEnum
        /// with all its required parameters
        /// (see http://msdn.microsoft.com/library/default.asp?  url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
        /// for full details or method signature) to
        /// retrieve a list of domain SV_TYPE_WORKSTATION
        /// and SV_TYPE_SERVER PC's
        /// </summary>
        /// <returns>Arraylist that represents
        /// all the SV_TYPE_WORKSTATION and SV_TYPE_SERVER
        /// PC's in the Domain
        /// </returns>
        public ArrayList getNetworkComputers()
        {
            //local fields

            ArrayList networkComputers = new ArrayList();
            const int MAX_PREFERRED_LENGTH = -1;
            int SV_TYPE_WORKSTATION = 1;
            int SV_TYPE_SERVER = 2;
            IntPtr buffer = IntPtr.Zero;
            IntPtr tmpBuffer = IntPtr.Zero;
            int entriesRead = 0;
            int totalEntries = 0;
            int resHandle = 0;
            int sizeofINFO = Marshal.SizeOf(typeof(_SERVER_INFO_100));


            try
            {
                //call the DllImport : NetServerEnum 
                //with all its required parameters
                //see http://msdn.microsoft.com/library/
                //default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
                //for full details of method signature

                int ret = NetServerEnum(null, 100, ref buffer,
                    MAX_PREFERRED_LENGTH,
                    out entriesRead,
                    out totalEntries, SV_TYPE_WORKSTATION |
                    SV_TYPE_SERVER, null, out 
                    resHandle);
                //if the returned with a NERR_Success 

                //(C++ term), =0 for C#

                if (ret == 0)
                {
                    //loop through all SV_TYPE_WORKSTATION 

                    //and SV_TYPE_SERVER PC's

                    for (int i = 0; i < totalEntries; i++)
                    {
                        //get pointer to, Pointer to the 
                        //buffer that received the data from the call to NetServerEnum. 
                        //Must ensure to use correct size of STRUCTURE to ensure correct 
                        //location in memory is pointed to
                        tmpBuffer = new IntPtr((int)buffer + (i * sizeofINFO));

                        //Have now got a pointer to the list 
                        //of SV_TYPE_WORKSTATION and 
                        //SV_TYPE_SERVER PC's, which is unmanaged memory
                        //Needs to Marshal data from an 
                        //unmanaged block of memory to a 
                        //managed object, again using 
                        //STRUCTURE to ensure the correct data
                        //is marshalled 
                        _SERVER_INFO_100 svrInfo = (_SERVER_INFO_100)Marshal.PtrToStructure(tmpBuffer, typeof(_SERVER_INFO_100));

                        //add the PC names to the ArrayList
                        networkComputers.Add(svrInfo.sv100_name);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Problem with acessing " + "network computers in NetworkBrowser " + "\r\n\r\n\r\n" + ex.Message,"Error", MessageBoxButtons.OK,MessageBoxIcon.Error);
                return null;
            }
            finally
            {
                //The NetApiBufferFree function frees the memory that the 
                //NetApiBufferAllocate function allocates
                NetApiBufferFree(buffer);
            }
            //return entries found
            return networkComputers;
        }

        private void bwNetworkStatus_DoWork(object sender, DoWorkEventArgs e)
        {
            ArrayList al = new ArrayList();
            al = getNetworkComputers();

            TcpClient TcpScan = new TcpClient();
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Host Name"));
            dt.Columns.Add(new DataColumn("IP Address"));
            dt.Columns.Add(new DataColumn("HTTP Server"));

            for (int index = 0; index < al.Count; index++)
            {
                string ip = GetIPAddress(al[index].ToString());
                int percentage = (int)(index * 100)/al.Count;

                bwNetworkStatus.ReportProgress(percentage);

                DataRow dr = dt.NewRow();
                dr[0] = al[index];
                dr[1] = ip;
                if (!ip.Equals(invalidIP))
                   dr[2] = checkHttpPorts(ip);
                dt.Rows.Add(dr);
            }

            e.Result = dt;
        }

        private void bwNetworkStatus_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        private void bwNetworkStatus_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            dgNetworkStatusList.DataSource = (DataTable)e.Result;
            lblScanning.Text = "Scanning Complete";
            this.Text = "Network Status";
            progressBar1.Value = 0;
        }

        bool _http_active = false;

        private bool checkHttpPorts(string ip)
        {
            TcpClient TcpScan = new TcpClient();
            ArrayList HttpPorts = new ArrayList();
            HttpPorts.Add(80);
            HttpPorts.Add(8080);

            Socket connector = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            foreach (int Port in HttpPorts)
            {
                Socket conector = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ipAddress = new IPAddress(IPAddressToLong(ip));
                EndPoint ep = new IPEndPoint(ipAddress, Port);

                try
                {
                    conector.Connect(ep);
                    _http_active = true;
                    break;
                }
                catch
                {
                    _http_active = false;
                }
            }
          return _http_active;
        }

 

        static public uint IPAddressToLong(string IPAddr)
        {
            System.Net.IPAddress oIP = System.Net.IPAddress.Parse(IPAddr);
            byte[] byteIP = oIP.GetAddressBytes();


            uint ip = (uint)byteIP[3] << 24;
            ip += (uint)byteIP[2] << 16;
            ip += (uint)byteIP[1] << 8;
            ip += (uint)byteIP[0];

            return ip;
        }
    }
}